/*
 * Copyright (c) 2007 T.Cogghe, D.Leroux, S.Lévignac, S.Rives
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
#include "IHM/IHM.hh"
#include "fenetreFichiers.hh"
#include "fenetreFinale.hh"
#include "fenetreAstres.hh"
#include "dialogueFichiers.hh"
#include "dialogueRepertoire.hh"
#include "dialogueQuitter.hh"
#include "editAstres.hh"
#include <gtkmm/targetentry.h>
#include <list>



ListeFichiers::ListeFichiers(BaseObjectType* cobject, const Glib::RefPtr<Gnome::Glade::Xml>& refGlade) : TreeView(cobject) {
	store = Gtk::ListStore::create( tmdl );
	set_model( store );
	append_column("Nom du Fichier",tmdl.fichier);
	append_column("Date EXIF",tmdl.date_exif);
	append_column("Date du Fichier",tmdl.date_fic);

	columns_autosize();
	set_headers_visible(true);
	set_headers_clickable(true);
	set_reorderable( true );
	set_rules_hint( true );
	//set_enable_search( true );

	selection = get_selection();

	selection->set_mode(Gtk::SELECTION_MULTIPLE);
}


class Decaleur {
private:
	std::vector<int>& layout;
	std::list<int> indices;
	std::list<Gtk::TreeModel::iterator> morituri;
	Glib::RefPtr<Gtk::ListStore>& store;
	Glib::RefPtr<Gtk::TreeSelection> selection;
	int delta;
public:
	Decaleur(std::vector<int>& l, Glib::RefPtr<Gtk::ListStore>& s,
		 Glib::RefPtr<Gtk::TreeSelection>& sl)
		: layout(l), store(s),  selection(sl) {}
	~Decaleur() {}

	void dump() {
		for(int z=0;z<(int)layout.size();z++) { cout<<layout[z]<<','; } cout<<endl;
	}

	void reset() {
		layout.clear();
		indices.clear();
//		cout<<"clear ";dump();
		store->foreach_path(sigc::mem_fun(*this,&Decaleur::reset_cb));
//		cout<<"init ";dump();
	}

	bool reset_cb(const Gtk::TreeModel::Path& path) {
		layout.push_back(-1);
		indices.push_back(path[0]);
		return false;
	}

	void decaleSel(int k) {
		if(selection->get_selected_rows().size()==0 || !k) {
			return;
		}
		reset();
		delta=k;
		selection->selected_foreach_path(sigc::mem_fun(*this,&Decaleur::shift_cb));
//		cout<<"shift ";dump();

		for(int i=0;i<(int)layout.size();i++) {
			if(layout[i]==-1) {
				layout[i]=indices.front();
				indices.pop_front();
			}
		}
//		cout<<"fill ";dump();

		store->reorder(Glib::ArrayHandle<int>(layout));
	}

	void detruitSel() {
		if(selection->get_selected_rows().size()==0) {
			return;
		}

		morituri.clear();
		selection->selected_foreach_iter(sigc::mem_fun(*this,&Decaleur::del_cb));

		std::list<Gtk::TreeModel::iterator>::iterator
			i=morituri.begin(),
			j=morituri.end();

		while(i!=j) {
			store->erase(*i);
			++i;
		}
	}

	void del_cb(const Gtk::TreeModel::iterator& i) {
		morituri.push_front(i);
	}

	void shift_cb(const Gtk::TreeModel::Path& path) {
	//	Gtk::TreeRow row = *path;
		int i=path[0]+delta;
		cout<<"sel_foreach ["<<path[0]<<"=>"<<i<<']'<<endl;
		if(i>=0&&i<(int)layout.size()&&layout[i]==-1) {
			layout[i]=path[0];
			indices.remove(path[0]);
		} else {
			layout[path[0]]=path[0];
			indices.remove(path[0]);
		}
		return;
	}

};



void ListeFichiers::selectionHaut() {
/*	cerr<<"TODO at "<<__FILE__<<" +"<<__LINE__<<endl;
	listeReset();
	selection->selected_foreach_path(sigc::mem_fun(*this,&ListeFichiers::sh_cb));
	for(unsigned int i=0,n=0;i<layout.size();i++) {
		if(layout[i]==-1) {
			layout[i]=n;
			++n;
		}
	}
	store->reorder(Glib::ArrayHandle<int>(layout));
*/
	Decaleur d(layout,store,selection);
	d.decaleSel(-1);
}


void ListeFichiers::selectionBas() {
	//cerr<<"TODO at "<<__FILE__<<" +"<<__LINE__<<endl;
	Decaleur d(layout,store,selection);
	d.decaleSel(1);
}





void ListeFichiers::selectionMoins() {
	//cerr<<"TODO at "<<__FILE__<<" +"<<__LINE__<<endl;
	Decaleur d(layout,store,selection);
	d.detruitSel();
}


/*
void ListeFichiers::sh_cb(const Gtk::TreeModel::Path& path) {
//	Gtk::TreeRow row = *path;
	cout<<"sel_foreach ["<<path[0]<<']'<<endl;
	int i=path[0]-1;
	if(i<0) {
		return;
	}
	if(i>=0&&i<layout.size()&&layout[i]==-1) {
		layout[i]=path[0];
	} else {
		layout[path[0]]=path[0];
	}
	return ;
}
*/





IHM::FenetreFichiers::FenetreFichiers(BaseObjectType* cobject, const Glib::RefPtr<Gnome::Glade::Xml>& refGlade)
	: Gtk::Window(cobject) //m_refGlade(refGlade),
{
	Gtk::Button*b;

	getWD(refGlade,listeFic,"listeFichiers");

	getW(refGlade,b_quitter,"b_Fic_Quitter");
	b_quitter->signal_clicked().connect(sigc::mem_fun(*this,&FenetreFichiers::quitter));
	getW(refGlade,b_valider,"b_Fic_Valider");
	b_valider->signal_clicked().connect(sigc::mem_fun(*this,&FenetreFichiers::valider));
	getW(refGlade,b,"b_Fic_ListeFichiers");
	b->signal_clicked().connect(sigc::mem_fun(*this,&FenetreFichiers::ajoutFichiers));
	getW(refGlade,b,"b_Fic_Repertoire");
	b->signal_clicked().connect(sigc::mem_fun(*this,&FenetreFichiers::ajoutRepertoire));

	getW(refGlade,b,"b_Fic_Haut");
	b->signal_clicked().connect(sigc::mem_fun(*listeFic,&ListeFichiers::selectionHaut));
	getW(refGlade,b,"b_Fic_Bas");
	b->signal_clicked().connect(sigc::mem_fun(*listeFic,&ListeFichiers::selectionBas));
	getW(refGlade,b,"b_Fic_Moins");
	b->signal_clicked().connect(sigc::mem_fun(*listeFic,&ListeFichiers::selectionMoins));

	getW(refGlade,chk_auto,"chkAutoDetect");

}

IHM::FenetreFichiers::~FenetreFichiers() {}

void IHM::FenetreFichiers::ajoutFichiers() {
	IHM::env->dFic->show();
}

void IHM::FenetreFichiers::ajoutRepertoire() {
	IHM::env->dRep->show();
}

void IHM::FenetreFichiers::quitter() {
	IHM::env->dQuit->show();
}






class SpawnFileList {
private:
	std::vector<std::string>&v;
public:
	SpawnFileList(vector<std::string>&a) : v(a) {
		v.clear();
		IHM::env->fFic->listeFic->store->foreach_iter(sigc::mem_fun(*this,&SpawnFileList::cb));
	}
	bool cb(Gtk::TreeModel::iterator i) {
		Gtk::TreeModel::Row row=*i;
		v.push_back(row.get_value(IHM::env->fFic->listeFic->tmdl.fichier));
		return 0;
	}
};




void IHM::FenetreFichiers::valider() {
	//static std::string img("night_sky.jpg");
//	static std::string img("images_test/stellarium0.png");
//	static Image i(Gdk::Pixbuf::create_from_file(img));
	SpawnFileList spawnFileList(IHM::env->fichiers);

	IHM::env->autoDetection=!chk_auto->get_active();

	/* création de la liste d'images */
	IHM::env->initListeImages(IHM::env->fichiers);

	if(!IHM::env->images.empty()) {
		IHM::env->imgDetection=0;

		if(IHM::env->edAs) delete IHM::env->edAs;
		IHM::env->edAs=new EditAstres(IHM::env->fAst->imgAstres,IHM::env->fAst->validAst);
		Image::Seuil k(IHM::env->images[0]);
		IHM::env->edAs->setImage(*IHM::env->images[0],k);
		IHM::env->edAs->griserValid();

		IHM::env->fAst->show();
	} else {
		cerr<<"liste d'images vide !"<<endl;
	}
}




